package com.dragon.utils;

import com.dragon.pojo.ExecuteMessage;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.util.concurrent.TimeUnit;

@Slf4j
public class ProcessUtils {

    private static final String SEPARATOR = "---MEMORY_SEPARATOR---";

    /**
     * 执行进程并获取信息，会解析一个特殊内存分隔符以获取内存使用情况。
     *
     * @param runProcess 要执行的进程。
     * @param opName     操作的描述性名称 (例如, "运行")。
     * @return 包含结果的 ExecuteMessage 对象。
     */
    public static ExecuteMessage runProcessAndGetMessage(Process runProcess, String opName,String input,long timeout) {
        ExecuteMessage executeMessage = new ExecuteMessage();

        try {

            // 分别读取标准输出和错误输出
            StringBuilder output = new StringBuilder();
            StringBuilder errorOutput = new StringBuilder();
            Thread outputThread = new Thread(() -> {
                try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(runProcess.getInputStream(),"GBK"))) {
                    String line;
                    while ((line = bufferedReader.readLine()) != null) {
                        output.append(line).append(" ");
                    }
                } catch (IOException e) {
                    log.error("读取标准输出时出错", e);
                }
            });

            Thread errorThread = new Thread(() -> {
                try (BufferedReader errorBufferedReader = new BufferedReader(new InputStreamReader(runProcess.getErrorStream(),"GBK"))) {
                    String line;
                    while ((line = errorBufferedReader.readLine()) != null) {
                        errorOutput.append(line).append(" ");
                    }
                } catch (IOException e) {
                    log.error("读取错误输出时出错", e);
                }
            });

            outputThread.start();
            errorThread.start();

            // 给程序输入
            if(input != null && !input.isEmpty()) {
                try(BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(runProcess.getOutputStream()))) {
                    writer.write(input);
                    writer.flush();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            long startTime = System.currentTimeMillis();
            boolean finishedInTime = runProcess.waitFor(timeout, TimeUnit.MILLISECONDS);
            long endTime = System.currentTimeMillis();

            // 如果超时
            if(!finishedInTime){
                // 先发送一个温和地终止请求
                runProcess.destroy();

                // 给它一点时间响应，还活着直接强制杀死
                if (!runProcess.waitFor(500, TimeUnit.MILLISECONDS)) {
                    runProcess.destroyForcibly();
                }
                executeMessage.setErrorMessage("Time Limit Exceeded");
                executeMessage.setTime(timeout); // 执行时间记录为超时时间
            } else {
                // 如果是正常结束，计算真实时间
                executeMessage.setTime(endTime - startTime);
            }
            // 等待输出线程完成
            outputThread.join();
            errorThread.join();

            int exitValue = runProcess.exitValue(); // 获取退出码
            executeMessage.setExitValue(exitValue);

            String finalOutput = output.toString();
            String finalErrorOutput = errorOutput.toString().trim();
            if(!finalErrorOutput.isEmpty()){
                executeMessage.setErrorMessage(finalErrorOutput);
            }


            if (exitValue == 0) {
                log.info("{}成功", opName);
            } else {
                log.info("{}失败, 错误码: {}", opName, exitValue);
                // 在 exitValue != 0 的情况下，也设置标准输出信息
                executeMessage.setMessage(finalOutput);
                log.info("错误信息: {}", finalErrorOutput);
            }
            // 解析输出以获取消息和内存
            String[] parts = finalOutput.split(" " + SEPARATOR + " ");
            if (parts.length > 1 && parts[1] != null && !parts[1].trim().isEmpty()) {
                executeMessage.setMessage(parts[0].trim());
                try {
                    long memory = Long.parseLong(parts[1].trim());
                    executeMessage.setMemory(memory);
                } catch (NumberFormatException e) {
                    log.error("从执行器输出解析内存失败: '{}'", parts[1], e);
                    executeMessage.setMessage(finalOutput); // 解析失败，使用原始输出
                }
            } else {
                // 如果未找到分隔符，则将整个输出视为消息
                executeMessage.setMessage(finalOutput.trim());
            }
            if (executeMessage.getMemory() != null) {
                log.info("峰值内存: {} KB", executeMessage.getMemory());
            }
        } catch (InterruptedException e) {
            log.error("执行进程时出错", e);
            throw new RuntimeException(e);
        } finally {
            if (runProcess.isAlive()) {
                runProcess.destroyForcibly();
            }
        }
        return executeMessage;
    }
}